package com.jacen.fzxs.util;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Dom2EntityUtil {

	private static final Logger logger = LoggerFactory.getLogger(Dom2EntityUtil.class);

	/**
	 * 将xml数据转为实体
	 * 
	 * @param obj
	 * @param data
	 */
	@SuppressWarnings("unchecked")
	public static void parseElement(Object obj, Element data) {
		try {
			Map<String, Field> fieldMap = new HashMap<String, Field>();
			Class<?> clazz = obj.getClass();
			while (!clazz.equals(Object.class)) {
				Field[] fields = clazz.getDeclaredFields();
				for (Field field : fields) {
					fieldMap.put(field.getName(), field);
				}
				clazz = clazz.getSuperclass();
			}
			List<Element> childElementList = data.elements();
			for (Element childElem : childElementList) {
				Field field = fieldMap.get(childElem.getName());
				if (field == null) {
					logger.error("找不到合适的属性来对应:" + childElem.getName());
					continue;
				}
				if (field.getType().equals(String.class) || field.getType().equals(Boolean.class)) {// 基础类型
					ClassUtil.setValue(obj, childElem.getName(), field.getType().cast(childElem.getText()),
							field.getType());
				} else if (field.getType().equals(Integer.class)) {
					ClassUtil.setValue(obj, childElem.getName(), Integer.parseInt(childElem.getText()), field.getType());
				} else if (field.getType().equals(Double.class)) {
					ClassUtil.setValue(obj, childElem.getName(), Double.parseDouble(childElem.getText()),
							field.getType());
				} else if (field.getType().equals(List.class)) {// list
					Class<?> type = field.getType();
					List<Object> childObjList = new ArrayList<Object>();
					// 先获取方法
					String methodName = "set" + childElem.getName().substring(0, 1).toUpperCase()
							+ childElem.getName().substring(1);
					Method method = obj.getClass().getMethod(methodName, type);
					Type[] types = method.getGenericParameterTypes();
					Type childType = ((ParameterizedType) types[0]).getActualTypeArguments()[0];
					Class<?> childClazz = Class.forName(childType.toString().substring(6));
					List<Element> sunElemList = childElem.elements();
					int size = sunElemList.size();
					for (int i = 0; i < size; i++) {
						Element sunElem = sunElemList.get(i);
						Object childObj = null;
						if (childClazz.equals(String.class)) {
							childObj = sunElem.getText();
						} else {
							childObj = childClazz.newInstance();
						}
						parseElement(childObj, sunElem);
						childObjList.add(childObj);
					}
					ClassUtil.setValue(obj, childElem.getName(), childObjList, field.getType());
				} else {// object
					Object childObj = field.getType().newInstance();
					parseElement(childObj, childElem);
					ClassUtil.setValue(obj, childElem.getName(), childObj, field.getType());
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			//throw new XmlFormatException("报文解析错误");
		}
	}

	/**
	 * 将实体格式化成xml元素
	 * 
	 * @param <T>
	 * @param t
	 * @param parentElement
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> void formatElement(T t, Element parentElement) {
		try {
			Class<?> clazz = t.getClass();
			while (!clazz.equals(Object.class)) {
				Field[] fields = clazz.getDeclaredFields();
				if (fields != null) {
					for (Field field : fields) {
						if (Modifier.isStatic(field.getModifiers())) {
							continue;
						}
						String fieldName = field.getName();
						Object fieldValue = ClassUtil.getValue(t, fieldName);
						if (fieldValue == null) {
							continue;
						}
						if (fieldValue instanceof String || fieldValue instanceof Boolean
								|| fieldValue instanceof Integer || fieldValue instanceof Double
								|| fieldValue instanceof Long || fieldValue instanceof Short) {// 基础类型
							Element childElem = parentElement.addElement(fieldName);
							childElem.setText(String.valueOf(fieldValue));
						} else if (fieldValue instanceof List<?>) {// List类型
							Element childElem = parentElement.addElement(fieldName);
							List<Object> childObjList = (List<Object>) fieldValue;
							for (Object childObj : childObjList) {
								Element sunElem = childElem.addElement(clazzNameToElemName(childObj.getClass()
										.getSimpleName()));
								if (childObj instanceof String || childObj instanceof Boolean
										|| childObj instanceof Integer || childObj instanceof Double
										|| childObj instanceof Long || childObj instanceof Short) {
									sunElem.setText(String.valueOf(childObj));
								} else {
									formatElement(childObj, sunElem);
								}
							}
						} else {
							Element childElem = parentElement.addElement(fieldName);
							formatElement(fieldValue, childElem);
						}
					}
				}
				clazz = clazz.getSuperclass();
			}
		} catch (Exception e) {
			e.printStackTrace();
			//throw new XmlFormatException("转为报文错误:" + e.getMessage());
		}
	}

	private static String clazzNameToElemName(String clazzName) {
		return clazzName.substring(0, 1).toLowerCase() + clazzName.substring(1);
	}

}
